package com.qs.commontools.utils.collection;

import java.text.NumberFormat;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 集合Map工具类
 * @author qiusuo
 * @since 2021-10-15
 */
public class MapUtils {

    private MapUtils() {
    }

    /**
     * 从指定Map对象中根据键获取Object类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @param <V> 值泛型
     * @return Object类型的值
     */
    public static <K, V> V getObject(Map<? super K, V> map, K key) {
        return map != null ? map.get(key) : null;
    }

    /**
     * 从指定Map对象中根据键获取String类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return String类型的值
     */
    public static <K> String getString(Map<? super K, ?> map, K key) {
        if (map != null) {
            Object answer = map.get(key);
            if (answer != null) {
                return answer.toString();
            }
        }

        return null;
    }

    /**
     * 从指定Map对象中根据键获取Boolean类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return Boolean类型的值
     */
    public static <K> Boolean getBoolean(Map<? super K, ?> map, K key) {
        if (map != null) {
            Object answer = map.get(key);
            if (answer != null) {
                if (answer instanceof Boolean) {
                    return (Boolean)answer;
                }

                if (answer instanceof String) {
                    return Boolean.valueOf((String)answer);
                }

                if (answer instanceof Number) {
                    Number n = (Number)answer;
                    return n.intValue() != 0 ? Boolean.TRUE : Boolean.FALSE;
                }
            }
        }

        return null;
    }

    /**
     * 从指定Map对象中根据键获取Number类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return Number类型的值
     */
    public static <K> Number getNumber(Map<? super K, ?> map, K key) {
        if (map != null) {
            Object answer = map.get(key);
            if (answer != null) {
                if (answer instanceof Number) {
                    return (Number)answer;
                }

                if (answer instanceof String) {
                    try {
                        String text = (String)answer;
                        return NumberFormat.getInstance().parse(text);
                    } catch (ParseException var4) {
                    }
                }
            }
        }

        return null;
    }

    /**
     * 从指定Map对象中根据键获取Byte类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return Byte类型的值
     */
    public static <K> Byte getByte(Map<? super K, ?> map, K key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Byte ? (Byte)answer : answer.byteValue();
        }
    }

    /**
     * 从指定Map对象中根据键获取Short类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return Short类型的值
     */
    public static <K> Short getShort(Map<? super K, ?> map, K key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Short ? (Short)answer : answer.shortValue();
        }
    }

    /**
     * 从指定Map对象中根据键获取Integer类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return Integer类型的值
     */
    public static <K> Integer getInteger(Map<? super K, ?> map, K key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Integer ? (Integer)answer : answer.intValue();
        }
    }

    /**
     * 从指定Map对象中根据键获取Long类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return Long类型的值
     */
    public static <K> Long getLong(Map<? super K, ?> map, K key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Long ? (Long)answer : answer.longValue();
        }
    }

    /**
     * 从指定Map对象中根据键获取Float类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return Float类型的值
     */
    public static <K> Float getFloat(Map<? super K, ?> map, K key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Float ? (Float)answer : answer.floatValue();
        }
    }

    /**
     * 从指定Map对象中根据键获取Double类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return Double类型的值
     */
    public static <K> Double getDouble(Map<? super K, ?> map, K key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Double ? (Double)answer : answer.doubleValue();
        }
    }

    /**
     * 从指定Map对象中根据键获取Map类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return Map类型的值
     */
    public static <K> Map<?, ?> getMap(Map<? super K, ?> map, K key) {
        if (map != null) {
            Object answer = map.get(key);
            if (answer != null && answer instanceof Map) {
                return (Map)answer;
            }
        }

        return null;
    }

    /**
     * 从指定Map对象中根据键获取Object类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @param <V> 值泛型
     * @return Object类型的值
     */
    public static <K, V> V getObject(Map<K, V> map, K key, V defaultValue) {
        if (map != null) {
            V answer = map.get(key);
            if (answer != null) {
                return answer;
            }
        }

        return defaultValue;
    }

    /**
     * 从指定Map对象中根据键获取String类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return String类型的值
     */
    public static <K> String getString(Map<? super K, ?> map, K key, String defaultValue) {
        String answer = getString(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取Boolean类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return Boolean类型的值
     */
    public static <K> Boolean getBoolean(Map<? super K, ?> map, K key, Boolean defaultValue) {
        Boolean answer = getBoolean(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取Number类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return Number类型的值
     */
    public static <K> Number getNumber(Map<? super K, ?> map, K key, Number defaultValue) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取Byte类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return Byte类型的值
     */
    public static <K> Byte getByte(Map<? super K, ?> map, K key, Byte defaultValue) {
        Byte answer = getByte(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取Short类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return Short类型的值
     */
    public static <K> Short getShort(Map<? super K, ?> map, K key, Short defaultValue) {
        Short answer = getShort(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取Integer类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return Integer类型的值
     */
    public static <K> Integer getInteger(Map<? super K, ?> map, K key, Integer defaultValue) {
        Integer answer = getInteger(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取Long类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return Long类型的值
     */
    public static <K> Long getLong(Map<? super K, ?> map, K key, Long defaultValue) {
        Long answer = getLong(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取Float类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return Float类型的值
     */
    public static <K> Float getFloat(Map<? super K, ?> map, K key, Float defaultValue) {
        Float answer = getFloat(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取Double类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return Double类型的值
     */
    public static <K> Double getDouble(Map<? super K, ?> map, K key, Double defaultValue) {
        Double answer = getDouble(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取Map类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param defaultValue 默认值
     * @param <K> 键泛型
     * @return Map类型的值
     */
    public static <K> Map<?, ?> getMap(Map<? super K, ?> map, K key, Map<?, ?> defaultValue) {
        Map<?, ?> answer = getMap(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    /**
     * 从指定Map对象中根据键获取boolean类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return boolean类型的值
     */
    public static <K> boolean getBooleanValue(Map<? super K, ?> map, K key) {
        return Boolean.TRUE.equals(getBoolean(map, key));
    }

    /**
     * 从指定Map对象中根据键获取byte类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return byte类型的值
     */
    public static <K> byte getByteValue(Map<? super K, ?> map, K key) {
        Byte byteObject = getByte(map, key);
        return byteObject == null ? 0 : byteObject;
    }

    /**
     * 从指定Map对象中根据键获取short类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return short类型的值
     */
    public static <K> short getShortValue(Map<? super K, ?> map, K key) {
        Short shortObject = getShort(map, key);
        return shortObject == null ? 0 : shortObject;
    }

    /**
     * 从指定Map对象中根据键获取int类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return int类型的值
     */
    public static <K> int getIntValue(Map<? super K, ?> map, K key) {
        Integer integerObject = getInteger(map, key);
        return integerObject == null ? 0 : integerObject;
    }

    /**
     * 从指定Map对象中根据键获取long类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return long类型的值
     */
    public static <K> long getLongValue(Map<? super K, ?> map, K key) {
        Long longObject = getLong(map, key);
        return longObject == null ? 0L : longObject;
    }

    /**
     * 从指定Map对象中根据键获取float类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return float类型的值
     */
    public static <K> float getFloatValue(Map<? super K, ?> map, K key) {
        Float floatObject = getFloat(map, key);
        return floatObject == null ? 0.0F : floatObject;
    }

    /**
     * 从指定Map对象中根据键获取double类型的值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @return double类型的值
     */
    public static <K> double getDoubleValue(Map<? super K, ?> map, K key) {
        Double doubleObject = getDouble(map, key);
        return doubleObject == null ? 0.0D : doubleObject;
    }

    /**
     * 从指定Map对象中根据键获取boolean类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @param defaultValue 默认值
     * @return boolean类型的值
     */
    public static <K> boolean getBooleanValue(Map<? super K, ?> map, K key, boolean defaultValue) {
        Boolean booleanObject = getBoolean(map, key);
        return booleanObject == null ? defaultValue : booleanObject;
    }

    /**
     * 从指定Map对象中根据键获取byte类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @param defaultValue 默认值
     * @return byte类型的值
     */
    public static <K> byte getByteValue(Map<? super K, ?> map, K key, byte defaultValue) {
        Byte byteObject = getByte(map, key);
        return byteObject == null ? defaultValue : byteObject;
    }

    /**
     * 从指定Map对象中根据键获取short类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @param defaultValue 默认值
     * @return short类型的值
     */
    public static <K> short getShortValue(Map<? super K, ?> map, K key, short defaultValue) {
        Short shortObject = getShort(map, key);
        return shortObject == null ? defaultValue : shortObject;
    }

    /**
     * 从指定Map对象中根据键获取int类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @param defaultValue 默认值
     * @return int类型的值
     */
    public static <K> int getIntValue(Map<? super K, ?> map, K key, int defaultValue) {
        Integer integerObject = getInteger(map, key);
        return integerObject == null ? defaultValue : integerObject;
    }

    /**
     * 从指定Map对象中根据键获取long类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @param defaultValue 默认值
     * @return long类型的值
     */
    public static <K> long getLongValue(Map<? super K, ?> map, K key, long defaultValue) {
        Long longObject = getLong(map, key);
        return longObject == null ? defaultValue : longObject;
    }

    /**
     * 从指定Map对象中根据键获取float类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @param defaultValue 默认值
     * @return float类型的值
     */
    public static <K> float getFloatValue(Map<? super K, ?> map, K key, float defaultValue) {
        Float floatObject = getFloat(map, key);
        return floatObject == null ? defaultValue : floatObject;
    }

    /**
     * 从指定Map对象中根据键获取double类型的值，获取不到返回设置的默认值。
     *
     * @param map 指定Map对象
     * @param key 键名称
     * @param <K> 键泛型
     * @param defaultValue 默认值
     * @return double类型的值
     */
    public static <K> double getDoubleValue(Map<? super K, ?> map, K key, double defaultValue) {
        Double doubleObject = getDouble(map, key);
        return doubleObject == null ? defaultValue : doubleObject;
    }

    /**
     * 转为{@code Map<String,Object>}类型。
     *
     * @param map 待转换的Map
     * @return 转换结果
     */
    public static Map<String,Object> toMapStrObj(Map map) {
        Set<String> keys = map.keySet();
        Map<String, Object> m = new HashMap<>();
        for (String key : keys) {
            m.put(key, MapUtils.getObject(map, key, null));
        }
        return m;
    }

}
